import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as p;

/// 图片文件头特征
const Map<String, String> _fileTypes = {
  'FF D8 FF': 'jpg', // JPEG (jpg)
  '00 00 02 00 00': 'tga', // TGA (未压缩)
  '00 00 10 00 00': 'tga', // TGA (压缩)
  '89 50 4E': 'png', // PNG (png)
  '47 49 46 38': 'gif', // GIF (gif)
  '46 4F 52 4D': 'iff', // IFF
  '49 49': 'tif', // TIFF (tif)
  '49 20 49': 'tif', // TIFF (tif)
  '4D 4D': 'tif', // TIFF (tif)
  '42 4D': 'bmp', // 位图(bmp)
  '41 43 31': 'dwg', // CAD (dwg)
  '38 42 50': 'psd', // Photoshop (psd)
  'D0 CF 11': 'vsd', // Visio 绘图
  '7E 42 4B 00': 'psp', // PaintShop Pro Image File
  '25 21 50 53 2D 41 64 6F 62 65': 'ps',
  '49 49 1A 00 00 00 48 45 41 50': 'crw', // Canon digital camera RAW file
  '01 00 00 00 58 00 00 00': 'emf', // Extended (Enhanced) Windows Metafile Format, printer spool file
  '00 00 01 00 00': 'ico', // 	Icon File
  '0A nn 01 01': 'pcx', // ZSOFT Paintbrush file(where nn = 0x02, 0x03, or 0x05)
  '0A 05 01 08': 'pcx', // PC Paintbrush(often associated with Quake Engine games)
  '01 FF 02 04 03 02': 'drw', // Micrografx vector graphic file
  '52 49 46 46': 'webp', // WebP
};

class DecodeUtil {
  /// 十六进制转十进制
  static int? _hexToInt(String hex) {
    int? val;
    if (hex.toUpperCase().contains('0X')) {
      String desString = hex.substring(2);
      val = int.tryParse('0x$desString');
    } else {
      val = int.tryParse('0x$hex');
    }
    return val;
  }

  /// 获取异或值
  static (String type, int xor)? getXor(Uint8List bytes) {
    for (var entry in _fileTypes.entries) {
      var key = entry.key;
      var value = entry.value;
      var eigenvalues = key.split(' ');
      List<int> eigenvalueList = [];
      for (var i = 0; i < eigenvalues.length; i++) {
        eigenvalueList.add(_hexToInt(eigenvalues[i])! ^ bytes[i]);
      }
      var first = eigenvalueList[0];
      if(eigenvalueList.skip(1).every((value) => value == first)) {
        return (value, first);
      }
    }
    return null;
  }

  /// 同步解码文件到指定路径上
  static Future<String> convert(String root, String input, String output, bool isCopy) async {
    String outputPath = '';
    var inputFile = File(input);
    var randomAccessFile = inputFile.openSync();
    randomAccessFile.lockSync();
    try {
      (String, int)? xors;
      if (input.endsWith('.dat') || p.extension(input) == '') {
        var partialBytes = randomAccessFile.readSync(10);
        xors = getXor(partialBytes);
      }
      if (xors != null || isCopy) {
        // 重置字节位置
        randomAccessFile.setPositionSync(0);
        if (xors != null) {
          outputPath = p.join(output, '微信解码文件', p.relative(p.setExtension(input, '.${xors.$1}'), from: root));
        } else {
          outputPath = p.join(output, '微信解码文件', p.relative(input, from: root));
        }
        debugPrint('输入路径：$input');
        debugPrint('输出路径：$outputPath');
        var outputFile = File(outputPath);
        if (!outputFile.existsSync()) {
          outputFile.createSync(recursive: true);
        }
        var iOSink = outputFile.openWrite();

        try {
          Uint8List buffer = Uint8List(1024 * 10);
          int length;
          while ((length = randomAccessFile.readIntoSync(buffer)) != 0) {
            for (var i = 0; i < buffer.length; i++) {
              if (xors != null) {
                buffer[i] = buffer[i] ^ xors.$2;
              }
              if (i == length - 1) {
                break;
              }
            }
            iOSink.add(buffer);
            await iOSink.flush();
          }
        } finally {
          await iOSink.flush();
          await iOSink.close();
        }
      }
    } finally {
      randomAccessFile.unlockSync();
      randomAccessFile.closeSync();
    }
    return outputPath;
  }
}
